package com.ce.tag;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;

import org.apache.struts2.views.jsp.ui.SelectTag;

import com.ce.framework.util.BeanAccessUtil;
import com.ce.framework.util.StringUtil;
import com.ce.util.TreeNode;

public abstract class AbstractSelectTag extends SelectTag {
	private static final long serialVersionUID = 1L;

//	private String name;
//
	protected String value;

	protected boolean readonly;
	
	/** 是过滤器使用文本做为存储值，默认为不使用 */
	protected boolean useText;

    protected String id;
//
//	protected String onchange;

	protected String style;

//	protected String cssClass;
	
	protected boolean blankOption;

	protected boolean allOption;
	
	protected LinkedHashMap<String,String> attr = new LinkedHashMap<String, String>();

	/**
	 * 附加的选项，以英文冒号和竖线分隔，格式：存储值1:显示文本1:序号1|存储值2:显示文本2:序号2|....
	 * 如文本或ID中用到冒号和竖线，可用&58;和&124;代替
	 */
	protected String otherOptions;

	
	protected List<Option> optList;
	
	public void release() {
		BeanAccessUtil.clearBeanProperties(this);
		attr = new LinkedHashMap<String, String>();
		super.release();
	}

	/**
	 * 开发人：andy 
	 * 开发日期: 2008-1-3 上午10:52:59 
	 * 功能描述: 方法的参数和返回值:
	 * 
	 * @return List中的元素是TreeNode
	 */
	abstract List<TreeNode> getContentList();

	@Override
	public int doStartTag() throws JspException {
		
		return SKIP_BODY;
	}
	
	protected void initData(){
		if (StringUtil.isBlank(value))
			value = this.getStack().findString(name);
		List<TreeNode> list2 = getContentList();
		ArrayList<TreeNode> contentList = new ArrayList<TreeNode>();
		if(list2!=null){
			contentList.addAll(list2);
		}
		ArrayList<Option> optionList = new ArrayList<Option>();
		ArrayList<Option> tailOptionList = new ArrayList<Option>();
		Option o = null;
		if(otherOptions==null){
			otherOptions = "";
		}
		if(blankOption){
			otherOptions = "::0|"+otherOptions;
		}
		if(allOption){
			otherOptions = ":全部:0|"+otherOptions;
		}
		if (StringUtil.isNotBlank(otherOptions)) {
			String[] tmp = otherOptions.split("\\|");
			for(int i=0;i<tmp.length;i++){
				if(tmp[i]==null)
					continue;
				String[] opt = tmp[i].split(":");
				if(opt.length<3)
					continue;
				o = new Option();
				o.setValue(tansString(opt[0]));
				o.setLabel(tansString(opt[1]));
				int seq = -1;
				try {
					seq = Integer.parseInt(opt[2]);
				} catch (NumberFormatException e) {
				}
				o.setSeq(seq);
				if (seq < 0)
					tailOptionList.add(o);
				else
					optionList.add(o);
			}
			Collections.sort(optionList, new Comparator<Option>() {
				public int compare(final Option o1, final Option o2) {
					final Option s1 = (Option) o1, s2 = (Option) o2;
					return s1.getSeq() - s2.getSeq();
				}
			});
		}
		optList = new ArrayList<Option>();
		int i = 0;
		while (optionList.size() > 0) {
			o = (Option) optionList.get(0);
			if (o.getSeq() > 0)
				break;
			optList.add(o);
			optionList.remove(0);
			i++;
		}
		if (contentList != null && contentList.size() > 0) {
			while (contentList.size() > 0) {
				if (optionList.size() > 0) {
					o = (Option) optionList.get(0);
					if (o.getSeq() == i) {
						optList.add(o);
						optionList.remove(0);
						i++;
						continue;
					}
				}
				TreeNode node = (TreeNode) contentList.get(0);
				optList.add(new Option(node.getVcId(),node.getVcName()));
				contentList.remove(0);
				i++;
			}
		}
		for (i = 0; i < tailOptionList.size(); i++) {
			o = (Option) optionList.get(i);
			optList.add(o);
		}
	}

	protected void writeHtml(){
		JspWriter out = pageContext.getOut();
		try {
			Option o = null;
			StringBuffer html = new StringBuffer();
			html.append("<select name=\"").append(name).append("\" ");
			if (id != null)
				html.append("id=\"").append(id).append("\" ");
			if (value != null)
				html.append(" value=\"").append(value).append("\" ");
			if (readonly)
				html.append(" readonly ");
			if (onchange != null)
				html.append(" onchange=\"").append(onchange).append("\" ");
			if (style != null)
				html.append(" style=\"").append(style).append("\" ");
			if (cssClass != null)
				html.append(" class=\"").append(cssClass).append("\" ");
			for(String k:attr.keySet()){
				html.append(" ").append(k);
				if(attr.get(k)!=null){
					html.append("=\"").append(attr.get(k).replace("\"", "\\\"").replaceAll("\\r|\\n", "")).append("\" ");
				}
			}
			html.append(">\n");
			for(Option opt:optList){
				addOption(html, opt.getValue(), opt.getLabel());
			}
			html.append("</select>");
			out.println(html.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public int doEndTag() throws JspException {
		initData();
		writeHtml();
		release();
		return SKIP_BODY;
	}
	
	public static String tansString(String src){
		if(src==null||src.indexOf("&")<0)
			return src;
		return src.replace("&58;", ":").replace("&124;", "|");
	}

	void addOption(StringBuffer html, String value, String label) {
		if(useText){
			value = label;
		}
		html.append("<option value=\"").append(value==null?"":value.trim()).append("\"");
		if (this.value != null && this.value.equals(value))
			html.append(" selected");
		html.append(">").append(label==null?"":label.trim()).append("</option>\n");
	}

	@Override
	public void setDynamicAttribute(String uri,String localeName,Object value) throws JspException {
		attr.put(localeName, ""+value);
	}

	public void setValue(String value) {
		this.value = value;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setOnchange(String onchange) {
		this.onchange = onchange;
	}

	public void setReadonly(boolean readonly) {
		this.readonly = readonly;
	}

	public void setStyle(String style) {
		this.style = style;
	}

	public void setUseText(boolean useText) {
		this.useText = useText;
	}

	public boolean isAllOption() {
		return allOption;
	}

	public void setAllOption(boolean allOption) {
		this.allOption = allOption;
	}

	public boolean isBlankOption() {
		return blankOption;
	}

	public void setBlankOption(boolean blankOption) {
		this.blankOption = blankOption;
	}

	public String getOtherOptions() {
		return otherOptions;
	}

	public void setOtherOptions(String otherOptions) {
		this.otherOptions = otherOptions;
	}

	public boolean isReadonly() {
		return readonly;
	}

	public String getStyle() {
		return style;
	}

	public boolean isUseText() {
		return useText;
	}

}

class Option {
	private String label;

	private String value;

	private int seq;
	
	public Option(){
	}

	public Option(String val,String label){
		value=val;
		this.label = label;
	}

	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		this.label = label;
	}

	public int getSeq() {
		return seq;
	}

	public void setSeq(int seq) {
		this.seq = seq;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

}